package cn.vetech.sync.elasticsearch.service.impl;

import cn.vetech.sync.elasticsearch.model.DatabaseTableModel;
import cn.vetech.sync.elasticsearch.model.IndexTypeModel;
import cn.vetech.sync.elasticsearch.service.DataService;
import cn.vetech.sync.elasticsearch.service.ElasticsearchService;
import cn.vetech.sync.elasticsearch.service.MappingService;
import cn.vetech.sync.elasticsearch.service.SyncService;
import com.google.common.collect.BiMap;
import com.google.common.collect.Maps;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class DataServiceImpl implements DataService {

    private static final String COLUMN_NAME = "COLUMN_NAME";
    private static final String DATA_TYPE = "DATA_TYPE";
    private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * logger
     */
    private static final Logger logger = LoggerFactory.getLogger(DataServiceImpl.class);
    /**
     * mappingService
     */
    @Autowired
    private MappingService mappingService;
    /**
     * es服务
     */
    @Autowired
    private ElasticsearchService elasticsearchService;
    /**
     * 数据库服务
     */
    @Autowired
    private SyncService syncService;

    @Override
    public List<Map<String, Object>> getMapping() {
        BiMap<DatabaseTableModel, IndexTypeModel> biMap = mappingService.getMapping();
        List<Map<String, Object>> ms = biMap.keySet().stream().collect(ArrayList::new, this::transData, ArrayList::addAll);
        return ms;
    }

    public void transData(ArrayList al, DatabaseTableModel dtm) {
        Map<String, Object> map = Maps.newHashMap();
        IndexTypeModel itm = mappingService.getIndexType(dtm);
        String pk = mappingService.getTablePrimaryKeyMap().get(dtm.getDatabase() + "." + dtm.getTable());
        long dbCount = syncService.getTableCount(dtm.getDatabase(), dtm.getTable());
        long esCount = 0;
        try {
            esCount = elasticsearchService.count(itm.getIndex(), itm.getType());
        } catch (Exception e) {
        }
        map.put("table", dtm.getTable());
        map.put("database", dtm.getDatabase());
        map.put("index", itm.getIndex());
        map.put("type", itm.getType());
        map.put("pk", pk);
        map.put("dbCount", dbCount);
        map.put("esCount", esCount);
        al.add(map);
    }

    public XContentBuilder getEsMapping(String type) {
        //type即是表名
        List<Map<String, Object>> tableDate = syncService.getTableData(type);
        if (CollectionUtils.isEmpty(tableDate)) {
            return null;
        }
        //转换数据库数据
        XContentBuilder mapping = null;
        try {
            mapping = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject(type)
                    .startObject("_all").field("enabled", false).endObject()
                    .startObject("properties");
            //处理数据库字段数据
            XContentBuilder finalMapping = mapping;
            tableDate.forEach(t -> transDbTypeToEsType(t, finalMapping));
            mapping.endObject().endObject().endObject();
        } catch (Exception e) {
            logger.error("建立索引模板" + type + "错误", e);
        }
        return mapping;
    }

    /**
     * 将数据库类型转换为es类型
     *
     * @param data    Map<String,Object>
     * @param mapping XContentBuilder
     * @return Map<String   ,   Object>
     */
    public void transDbTypeToEsType(Map<String, Object> data, XContentBuilder mapping){
        Map<String, Object> newDate = Maps.newHashMap();
        String type = null;
        String format = null;
        String dbType = data.get(DATA_TYPE).toString();
        String name = data.get("COLUMN_NAME").toString();//数据库字段
        newDate.put("index", "analyzed");
        switch (dbType) {
            case "date":
                format = "yyyy-MM-dd";
                type = "date";
                newDate.put("format", format);
                newDate.put("index", true);
                break;
            case "datetime":
                format = "yyyy-MM-dd HH:mm:ss";
                type = "date";
                newDate.put("format", format);
                newDate.put("index", true);
                break;
            case "long":
            case "int":
            case "double":
            case "float":
                type = dbType;
                break;
            case "text":
            case "varchar":
            case "char":
                type = "keyword";
                break;
            default:
                type = "keyword";
                break;
        }
        newDate.put("type", type);
        newDate.put("store", "true");
        try {
            mapping.startObject(name);
            for (String key:newDate.keySet()){
                mapping.field(key, newDate.get(key));
            }
            mapping.endObject();
        } catch (Exception e) {
            logger.error("es field 出错.",e);
        }
    }

}
